[toc]
无连接通信(Verbindungslose Kommunikation)
无连接通信(Verbindungslose Kommunikation)的通道(Kanäle)可以按照带宽(Bandbreite)分成2种:
- 窄带通道(Schmalbandige Kanäle)
- 宽带通道(Breitbandige Kanäle)
窄带通道(Schmalbandige Kanäle)
窄带通道(Schmalbandige Kanäle)
只传输少量信息(wenige Bits),主要用于事件的通知(Melden von Ereignissen)。它需要同步机制和中断机制(Synchronisationskonzepte und Unterbrechungskonzepte )来确保通信的可靠性。
Linux里的例子:Signals
进程可以互相发送信号(使用 kill() )
进程可以显式捕获这些信号(使用 signal() ):
可以通过注册一个信号处理函数(signal handler)来处理信号
也忽略该信号(使用 SIG_IGN)
- 如果一个进程没有捕获(abfangen)信号,那么操作系统会终止(beendet)该进程。
- SIGKILL 和 SIGSTOP 是不能被捕获的,这些信号会强制终止或暂停进程,进程无法阻止或忽略它们
kill()函数的用法:
kill(pid, signal),其中pid是进程ID,signal是具体要发送的信号,可选的有:
信号名 | 作用说明 |
---|---|
SIGHUP | 终端挂起或控制进程终止,常用于重新加载配置 |
SIGINT | 中断(通常来自 Ctrl+C) |
SIGILL | 非法指令,通常是程序错误导致 |
SIGABRT | 异常终止(由 abort() 触发) |
SIGKILL | 强制终止,无法被捕获或忽略 |
SIGUSR1 | 用户自定义信号 1 |
SIGSEGV | 段错误(Segmentation Fault) |
SIGUSR2 | 用户自定义信号 2 |
SIGPIPE | 管道破裂(写入没有读取端的 pipe) |
SIGALRM | 定时器信号(alarm() 到期触发) |
SIGTERM | 正常终止请求,默认的 kill 信号 |
SIGCHLD | 子进程结束时通知父进程 |
SIGCONT | 恢复被停止的进程 |
SIGSTOP | 强制停止,无法被捕获或忽略 |
SIGTSTP | 终端停止信号(Ctrl+Z) |
代码示例:
1 |
|
输出示例:
1 | Counting 0... |
宽带通道(Breitbandige Kanäle)
宽带通道(Breitbandige Kanäle)
用于传输大量数据,可以根据通信的方式进一步划分为:
- 隐式通信(Implizite Kommunikation)
- 显式通信(Explizite Kommunikation)
隐式通信(Implizite Kommunikation)
隐式通信(Implizite Kommunikation)
是通过共享资源实现的,比如说内存、寄存器、文件、环形缓冲区等。
优点:简单快速,因为不需要不需要在不同地址空间(Adressräumen)之间复制数据。
缺点:不一定一直都有共享区域可以用;可能会出现 busy-waiting,所以需要额外的同步机制。
(第三章的内容就是在讲这个)
而隐式通信(Implizite Kommunikation) 可以进一步划分为:
同步通信(Synchrone Kommunikation)
发送方或接收方可能需要等待对方。
比如说共享内存并且设置了同步机制。
异步通信(Asynchrone Kommunikation)
发送和接收可以独立进行。
比如说通过共享的文件进行kommunizieren。
显式通信(Explizite Kommunikation)
显式通信(Explizite Kommunikation)
则是我们比较熟悉的:发送/接收信息。适用于地址空间(Adressräumen)分离的进程(比如两个互不相干的进程),不过是与操作系统的直接交互。
这种通信可以是本地的也可以是远程的。
一般信息由2部分组成:
- 消息头(Nachrichtenkopf,header):包含管理信息,比如说发送者、接收者的标识、消息大小等。
- 消息体(Nachrichtenkörper):有效载荷(payload),也就是真正的信息内容。
流程:
- 进程使用 send() 发送消息
- 操作系统的消息服务负责传递该消息
- 接收方进程使用 recv() 接收该消息
而显式通信(Explizite Kommunikation) 同样可以进一步划分为:
同步通信(Synchrone Kommunikation)
发送方或接收方可能需要等待对方
异步通信(Asynchrone Kommunikation)
发送和接收可以独立进行
这其中又有2种消息通信的模式(Muster):
消息通知(Meldung)
是单向的(unidirectional),通常只是传递少量数据,比如说通知状态变化。
任务(Auftrag)
是双向的(bidirectional),比如说查询某些数据,请求发送后收到包含数据的响应。
Asynchron的优点:
- 在实时系统中非常有用,当发送进程不能被阻塞时;
- 允许发送方和接收方并行处理任务;
- 适合用于事件的通知/信号传递。
Asynchron的缺点:
- 操作系统有管理负担(需要消息缓冲区来存储异步数据)
- 错误处理更复杂:
- 无法直接通知发送方是否成功;
- 数据包可能丢失(当缓冲区满了,尤其是网络通信中);
- 有时需要重传数据包。
在实际应用中,异步通信更常用,特别适用于不确定接收方是否在线、或者无法预测响应时间的情况。
可以使用线程来结合同步与异步通信(比如:主线程同步处理、子线程异步等待)。
Asynchrone Meldung
:
只发不等
Synchrone Meldung
:
等待对方确认收到
流程:
- 接收方在收到消息后会发送一个确认(Bestätigung)
- 发送方在发送完消息后会等待接收确认(Empfangsbestätigung)
确认消息不包含实际数据,仅用于同步。
另一种方法:Rendezvous-Verfahren:
- 在交换消息之前,发送方与接收方都要事先准备好进行发送和接收
- 这样一来消息不需要缓冲
Asynchrone Auftrag
:
各发各的
任务(Auftrag)和结果(Resultat)是作为两个独立的消息发送的。
Synchrone Auftrag
:
等待对方回复
Streams
流(Stream)是对连接(Verbindung)的一种抽象。
消息在传输过程中被缓冲,所有消息被整合为逻辑上的字节流(byte stream)。
操作系统可以建立/关闭连接,或者是在流中进行读/写操作。
C++头文件中的
1 |
指的就是这个。
而管道(Pipes)正是流(Stream)的实现。
管道是一个单向的流(unidirektionaler Strom)。双向通信可以用两个管道来模拟。管道实现先进先出(FIFO) 的数据传输模型。
管道(Pipes)一般分为2种:
(匿名)管道
pipe() 函数会创建一个管道,它返回两个文件描述符,分别用于读和写。
可以在 fork() 创建子进程时,把其中一端交给子进程,实现进程间通信,或者在不同的线程之间使用。
命名管道(Named Pipes)
用于多个进程之间的通信,它们有自己的名字,在文件系统中可见。
代码示例:
1 | int main() { |
1 | void sendData(int fd) { |
1 | void receiveData(int fd) { |
例题
例题1
Für wehlche der folgenden IPC-Mechanismen wird in der Regel ein Filedescriptor verwendent?
- Sockets
- Shared Memory
- Anon. Pipes
- Named Pipes
- Signals
答案:1,3,4。